package com.example.demo;

import com.example.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * AOP 演示类 - 演示"织入（Weaving）"的效果
 * 
 * CommandLineRunner接口让这个类在Spring Boot启动后自动执行
 * 我们将看到Spring如何将切面逻辑"织入"到目标对象中
 */
@Component
@Order(1)  // 先执行硬编码切点演示
public class AopDemo implements CommandLineRunner {

    @Autowired
    private UserService userService; // 注入的实际上是一个代理对象！

    @Override
    public void run(String... args) throws Exception {
        System.out.println("🌟 ========== Spring AOP 核心概念演示 ==========");
        System.out.println("📚 本演示将展示以下AOP核心概念：");
        System.out.println("   1. 切面（Aspect）：UserServiceAspect类");
        System.out.println("   2. 连接点（Joinpoint）：UserService的各个方法");
        System.out.println("   3. 通知（Advice）：前置、后置、环绕、异常、最终通知");
        System.out.println("   4. 切点（Pointcut）：定义在哪些方法上应用通知");
        System.out.println("   5. 织入（Weaving）：Spring创建代理对象的过程");
        System.out.println();

        // 检查织入结果 - 证明Spring创建了代理对象
        System.out.println("🔍 检查织入结果：");
        System.out.println("   目标对象类型: " + userService.getClass().getName());
        System.out.println("   是否为代理对象: " + (userService.getClass().getName().contains("$$")));
        System.out.println();

        // 演示1：正常方法调用 - 触发前置、后置、最终通知
        System.out.println("📋 【演示1】正常方法调用 - 观察通知执行顺序");
        System.out.println("═══════════════════════════════════════════════");
        String result1 = userService.createUser("张三", "zhangsan@example.com");
        System.out.println("📄 最终返回结果: " + result1);

        System.out.println("\n\n");

        // 演示2：删除方法调用 - 触发专门的删除通知
        System.out.println("📋 【演示2】删除方法调用 - 观察参数注入");
        System.out.println("═══════════════════════════════════════════════");
        boolean result2 = userService.deleteUser(1L);
        System.out.println("📄 删除结果: " + result2);

        System.out.println("\n\n");

        // 演示3：异常方法调用 - 触发异常通知
        System.out.println("📋 【演示3】异常方法调用 - 观察异常通知");
        System.out.println("═══════════════════════════════════════════════");
        try {
            userService.updateUser(-1L, "新名称"); // 传入非法参数触发异常
        } catch (Exception e) {
            System.out.println("💔 捕获到业务异常: " + e.getMessage());
        }

        System.out.println("\n\n");

        // 演示4：查询方法调用 - 没有环绕通知
        System.out.println("📋 【演示4】查询方法调用 - 只有基本通知");
        System.out.println("═══════════════════════════════════════════════");
        String result4 = userService.getUserInfo(100L);
        System.out.println("📄 查询结果: " + result4);

        System.out.println("\n\n🎉 AOP 演示完成！");
        System.out.println("📝 总结：");
        System.out.println("   ✅ 切面成功织入到目标对象中");
        System.out.println("   ✅ 各种类型的通知都正确执行");
        System.out.println("   ✅ 切点表达式精确匹配目标方法");
        System.out.println("   ✅ 横切关注点与业务逻辑完全分离");
    }
} 